﻿var played={}, 
mysql=require('mysql'),
http=require('http'),
url=require('url'),
crypto=require('crypto'),
querystring=require('querystring'),
config=require('./config.js'),
calc=require('./kj-data/kj-calc-time.js'),  //开奖时间模计算
exec=require('child_process').exec,
execPath=process.argv.join(" "),   //执行路径
parse=require('./kj-data/parse-calc-count.js');
require('./String-ext.js');
var client_dblib = false; //新加一个数据库连接对象
var fs = require('fs');
var express = require('express');
var app = express();
//日志跟踪 
var logger = require('tracer').console({
	transport : function(data) {		
		fs.open(__dirname + '/log/file_rum_timer.log', 'a', 0666, function(e, id) {
			fs.write(id, data.output+"\n", null, 'utf8', function() { fs.close(id, function() { }); });
		}); },
	format : ["{{timestamp}} ({{file}}:{{line}}) {{message}}",{error : "{{timestamp}} <{{title}}> {{message}} (in {{file}}:{{line}})\nCall Stack:\n{{stack}}" } ],
	dateformat : "yyyy/mm/dd HH:MM:ss",
});

// 抛出未知出错时处理
process.on('uncaughtException', function(e){
	console.log("报错了!!!提示信息:");
	console.log(e.stack);
});


//查询SQL操作
var QuerySQL = function(sqlstr,fun_callback){
	if(false == client_dblib || !client_dblib) return false ;
	client_dblib.query(sqlstr,function queryTb(err, results, fields) {
	    return fun_callback(err , results); //client_dblib.end(); 
	  }
	);
	return false ;
}




// 自动重启
if(config.restartTime){
	setTimeout(function(exec, execPath){
		exec(execPath);
		process.exit(0);
	}, config.restartTime * 3600 * 1000, exec, execPath);
}
var timers={};		// 任务记时器列表,存两个字段
var encrypt_key='cc40bfe6d972ce96fe3a47d0f7342cb0';
var timeConfig ;
var LotteryList = new Array();
var LotteryConfig; //彩种配置信息全局函数

//开始运行任务
var StartRumTask = function (){	
	console.log("启动定时执行计划===>>>>");
	if(null !=LotteryConfig && LotteryConfig != undefined && LotteryConfig ){
		logger.log("启动定时执行计划===>>>>");
		for(var key in LotteryConfig){
			var lotteryCg = LotteryConfig[key];
			if(null != lotteryCg && undefined != typeof(lotteryCg) && lotteryCg.lotterytype != ""){
				var lottery_name = lotteryCg.lotterytype;
				timers[lottery_name]={};
				timers[lottery_name][lottery_name] = {"timer":null,"option":lotteryCg};
				try{
					if( lotteryCg.status == "1") { 	//启动状态
						logger.log("启动["+ lottery_name +"]采集====>>>>>>>");
						runLoadResult(lotteryCg); 	//采集开始
					}
				} catch(err){
					logger.log("当前彩种["+ lottery_name +"]启动失败，暂停执行");
				}
			}
			
		}
	} else { 
		console.log("执行任务启动===>>>>失败， 5分钟后重启!");
		logger.log("执行任务启动 === StartRumTask >>>>  5分钟后重启!!!");
		setTimeout(StartRumTask,300 * 1000); //15秒之后再调用
	}
}

//获取配置函数
var GetRumTimerConfigList = function(){
	console.log("OPEN=====>GetRumTimerConfigList on!");
	http.get("http://" + config.baseUrl +"/gather/connect_mysql_setting?sign=CC38297DDCFD236FC147DFFB21B8B4D3", function(res) {  
		var dataStr = "";
		res.on('data', function(data) {   //数据读取事件
			dataStr += data.toString();  
		});  
		res.on('error', function(e) {   //错误产生事件
			    console.log("Got error: " + e.message);  
		});
		res.on('end', function() {  //请求结束事件绑定
			try {
				var config_obj = JSON.parse(dataStr);    //时间配置
				if(null == config_obj || config_obj.code != 200 || !config_obj.data){
					throw "获取DB配置异常";
				}
				var DBConfig = config_obj.data;    //时间配置
				if(null != DBConfig && DBConfig.host != "" && DBConfig.user != ""){
					console.log("获取DB配置=====>成功");
					defConfig = {host:DBConfig.host,user: DBConfig.user,password:DBConfig.password,port:DBConfig.port,database:DBConfig.database};
					client_dblib = mysql.createConnection(defConfig);	//创建DB连接   
					client_dblib.connect(); 							//DB连接   
					//client_dblib.query("USE "+ DBConfig.database);
					//StartRumTask(); //启动定时任务脚本运行开始
					
					//测试数据库连接是否正常
					var consql = 'SELECT * FROM qc_result_list ORDER BY tjData DESC LIMIT 10';
					
					//var consql = "delete FROM qc_result_list where tjData = '201810250207' and typeName = 'JSFT' ";
					$plist = QuerySQL(consql,function(errinfo,results){
						if(errinfo && null != errinfo.message){
							throw errinfo.message ; //出错情况 
						}
						for(var i = 0; i < results.length; i++)
				        {
				    		console.log("%d\t%s\t%s\t%s",results[i].resId,results[i].typeName + "(" + results[i].type + ")",results[i].proName,results[i].codes);
				        }
					});
				}else{
					console.log("获取DB配置=====>失败!");
				}
			}catch(err){ //重启服务
				logger.log(err); 
				logger.log("数据异常，等待5秒重新启动！！"); 
				console.log("数据异常，等待5秒重新启动！！" + err);
				setTimeout(GetRumTimerConfigList, 5000);
			}
		});  
	});
}


 


//请求函数
http.request=(function(_request){
	return function(options,callback){
		var timeout=options['timeout'],
			timeoutEventId;
		var req=_request(options,function(res){
			res.on('end',function(){
				clearTimeout(timeoutEventId);
				//console.log('response end...');
			});
			res.on('close',function(){ //请求结束
				clearTimeout(timeoutEventId);
				//console.log('response close...');
			});
			res.on('abort',function(){
				//console.log('abort...');
			});
			callback(res);
		});
		//超时
		req.on('timeout',function(){
			//req.res && req.res.abort();
			//req.abort();
			req.end();
		});
		
		//如果存在超时
		timeout && (timeoutEventId=setTimeout(function(){
			req.emit('timeout',{message:'have been timeout...'});
		},timeout));
		return req;
	};
})(http.request);


//启动函数
GetRumTimerConfigList(); 

//重启任务
var restartTask = function (lottConfig, sleep, flag){
	var lottery_name = lottConfig.lotterytype ; 	//彩种类型
	if(sleep <= 0) sleep = config.errorSleepTime;	//休息时间
	if(null == lottery_name || lottery_name == "") return false ;
	if(!timers[lottery_name]) timers[lottery_name]={};
	if(!timers[lottery_name][lottery_name]) timers[lottery_name][lottery_name]={"timer":null,"option":lottConfig};
	if(flag){
		for(var t in timers[lottery_name]){
			var opt=timers[lottery_name][t].option;			
			clearTimeout(timers[lottery_name][lottery_name].timer);
			timers[lottery_name][lottery_name].timer = setTimeout(runLoadResult, sleep*1000, opt);		//重新启动单个类型
		}
	}else{
		clearTimeout(timers[lottery_name][lottery_name].timer);
		timers[lottery_name][lottery_name].timer = setTimeout(runLoadResult, sleep * 1000, lottConfig); //重新启动单个类型
	}
}

//启动采集数据的采集工作
var runLoadResult = function(lottConfig){
	var tjLotteryType = lottConfig.lotterytype ; //当前采票类型
	if(null != tjLotteryType  && tjLotteryType != ""){
		console.log("采集："+ tjLotteryType +"=====>开奖数据，请稍候...");
		logger.log("采集："+ tjLotteryType +"=====>开奖数据，请稍候...");
		//定时器清理
		if(timers[tjLotteryType][tjLotteryType].timer) {
			clearTimeout(timers[tjLotteryType][tjLotteryType].timer);
		}
		var myDate = new Date();                          		//当前时间
		var nowStamp = myDate.getTime();                       	//获取当前时间的时间戳
		
		//请求采集接口======>>>>采集指定彩种的数据
		var ApiOption =  {  
			"host":config.baseUrl,
			"timeout" : 30000,
			"path":'/gather/httpApiOpen?lottery=' + tjLotteryType + "&t="+nowStamp,         
			"headers":{"User-Agent":"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) " }
		};
		//HTTP发起
		http.request(ApiOption, function(request){
			var lastdata="";
			request.on("data", function(_data){
				lastdata += _data.toString();
				logger.log('返回数据：'+tjLotteryType+'====>'+ lastdata.substring(0,50));
			});
			request.on("end", function(){
				logger.log('采集结果：'+tjLotteryType+'====>处理中....');
				try{
					if(lastdata && lastdata.indexOf('<head>') > 0){ //页面异常，出错 
						restartTask(lottConfig, 60);
						logger.log('Page出错：'+tjLotteryType+' ====> 等待6 秒后重启');
						return ;
					}
					logger.log(lastdata);
					var result = JSON.parse(lastdata);	//采集结果处理，逻辑
					var httpStatus = result.code;
					if(null != result && httpStatus != "" && httpStatus == '1'){ //接口成功；
						var cjData = result.data;					//采集结果
						var isOpen = parseInt(cjData.needCaiji);	//是否开奖成功，0-为成功能不要采集，1-继续采集
						var proNo = cjData.proNo;	//是否开奖成功，0-为成功能不要采集，1-继续采集
						var nextLeftTime = (cjData.leftTime != "") ? parseInt(cjData.leftTime) : 0;	//下一次采集时间启动；
						//已开奖，就固定时间重启;
						if(isOpen == 0 && nextLeftTime > 0){ //固定时间启动；
							console.log('[第'+ proNo+'期]开奖SUCCESS：'+tjLotteryType+' 启动推送====> 等待重启：' + nextLeftTime + " 秒后");
							logger.log('[第'+ proNo+'期]开奖OK,Waiting!'+tjLotteryType+' ====> 等待重启：' + nextLeftTime + " 秒后");
							//时隔太长的情况下可以分隔;;超过5个小时，则拆成5个时间段
							if(nextLeftTime && nextLeftTime > 5 * 3600){  nextLeftTime = parseInt(nextLeftTime / 5) ; }
							logger.log('开奖SUCCESS，启动推送功能：'+tjLotteryType+'====>推送测试');							
							restartTask(lottConfig , nextLeftTime);
							return ;
						}else{
							logger.log('[第'+ proNo+'期]开奖中………：'+tjLotteryType+' ====> 即奖重启：' + nextLeftTime + " 秒后=====暂停中 ");
							restartTask(lottConfig ,nextLeftTime);	// 默认重启
						}
					}else{ 
						//接口数据异常;每分钟一次
						logger.log('采集失败：'+ tjLotteryType + ',当前状态Status=['+ httpStatus +']====>' + result.msg);
						restartTask(lottConfig , 60); //可重启：暂无资源可用
					}
				}catch(err){
					logger.log('运行出错：%s，休眠%f秒'.format(err, config.errorSleepTime));
					restartTask(lottConfig, config.errorSleepTime);
				}
			});
			request.on("error", function(err){
				logger.log('解析：'+tjLotteryType+'结果出错====>');
				logger.log(err);
				restartTask(lottConfig,300);
			});			
		}).on('timeout', function(err){
			console.log('开始采集'+tjLotteryType+'数据超时');	//数据超时
			logger.log('开始采集'+tjLotteryType+'数据超时');
		}).on("error", function(err){
			logger.log('开始采集'+tjLotteryType+'====>网络错误');//一般网络出问题会引起这个错
			logger.log(err);
			restartTask(lottConfig,120);
		}).end();
	}
}
function createMySQLClient(){
	try{
		return mysql.createClient(config.dbinfo).on('error', function(err){
			throw('连接数据库失败');
		});
	}catch(err){
		log('连接数据库失败：'+err);
		return false;
	}
}
//重启操作
app.get('/restart', function(req, res){
	//重新启动采集工作
	for(var key in LotteryConfig){
		var conf = LotteryConfig[key];
		clearTimeout(timers[conf.lotterytype][conf.lotterytype].timer);
	}
	setTimeout(StartRumTask, 5000); 
	res.send('success');
});

var server = app.listen(3000, function() {
	//logger.log("Listening on port 3000");
    //console.log('It is Listening on port %d', server.address().port);
}); 